package com.ticket.sass.provider.business.impl;


import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ticket.sass.common.entity.provider.AdminEntity;
import com.ticket.sass.common.exception.enums.ErrorCode;
import com.ticket.sass.common.exception.exception.BadRequestException;
import com.ticket.sass.provider.business.AdminBusiness;
import com.ticket.sass.provider.config.AppConfig;
import com.ticket.sass.provider.dto.input.admin.AdminAddInput;
import com.ticket.sass.provider.dto.input.admin.AdminListInput;
import com.ticket.sass.provider.dto.input.admin.AdminLoginInput;
import com.ticket.sass.provider.dto.input.admin.AdminUpdInput;
import com.ticket.sass.provider.dto.output.admin.AdminInfoOutput;
import com.ticket.sass.provider.dto.output.admin.AdminListOutput;
import com.ticket.sass.provider.service.PageModel;
import com.ticket.sass.provider.service.impl.AdminServiceImpl;
import com.ticket.sass.provider.util.*;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.modelmapper.TypeToken;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;


/**
 * 管理员业务
 * @author ywb
 * @date 2021-11-25 18:16
 */
@Slf4j
@Service
@AllArgsConstructor
public class AdminBusinessImpl implements AdminBusiness {
    
    final JwtUtil jwtUtil;
    final ModelUtil modelUtil;
    final AdminServiceImpl adminService;

    @Override
    public void add(AdminAddInput input){
        validateAdmin(null, input.getUsername());
        
        AdminEntity admin = modelUtil.mapToMap(input, AdminEntity.class);
        admin.setPassword(new BCryptUtil(AppConfig.PWD_SECRET).encrypt(admin.getPassword()));
        
        adminService.save(admin);
    }

    @Override
    public PageModel<AdminListOutput> list(AdminListInput input) {
        IPage<AdminEntity> page = adminService.iPage(AdminEntity.class, input);
        List<AdminListOutput> outputs = modelUtil.listToList(
            page.getRecords(),
            new TypeToken<List<AdminListOutput>>(){}.getType()
        );

        return new PageModel<>(page.getTotal(), outputs);
    }

    @Override
    public void upd(AdminUpdInput input) {
        validateAdmin(input.getId(), input.getUsername());
        AdminEntity admin = modelUtil.mapToMap(input, AdminEntity.class);
        String password = admin.getPassword();
        if (!StrUtil.isEmpty(password)){
            admin.setPassword(new BCryptUtil(AppConfig.PWD_SECRET).encrypt(password));
        }
        adminService.updateById(admin);
    }

    @Override
    public TokenModel login(AdminLoginInput input) {
        // 用户名 是 唯一的 根据用户名查询到用户
        AdminEntity admin = adminService.getOne(new QueryWrapper<AdminEntity>().eq("username", input.getUsername()));

        // 登录成功
        if (
            Objects.nonNull(admin) &&
            admin.getEnable() &&
            new BCryptUtil(AppConfig.PWD_SECRET).check(input.getPassword(), admin.getPassword())
        ){
            return jwtUtil.createToken(admin.getId(), admin.getUsername());
//            AdminInfoOutput output = new AdminInfoOutput(admin.getId(), admin.getUsername(), admin.getEnable(), tenantId, cinemaService.getLabModels(new QueryWrapper<CinemaEntity>().in(cinemaIds.size() > 0, "id", cinemaIds)));
            
            // 成功存入redis 中 将权限一起保存
//            redisCache.setCacheObject(jwtUtil.validTokenCacheKey(admin.getId()), output.toJson(), 1, TimeUnit.DAYS);
        } else {
            throw new BadRequestException(
                ErrorCode.LOGIN_PARAMS_ERROR,
                ErrorCode.LOGIN_PARAMS_ERROR.getReasonPhrase()
            );
        }
//        return jwtUtil.createToken(admin.getId(), admin.getUsername());
    }
    
    @Override
    public AdminInfoOutput info() {
        Long id = jwtUtil.getAudBy(ResponseUtil.getRequest());
        AdminEntity admin = adminService.getById(id);
//        String cacheObject = redisCache.getCacheObject(jwtUtil.validTokenCacheKey(id));
//        return GsonUtil.getInstance().fromJson(cacheObject, AdminInfoOutput.class);
       return modelUtil.mapToMap(admin, AdminInfoOutput.class);
    }

    private void validateAdmin(Long id, String username) {
        // 如果 id 为空，表示是新增操作
        if (id == null) {
            // 检查是否存在相同的用户名
            if (adminService.count(new QueryWrapper<AdminEntity>().eq("username", username)) > 0) {
                throw new BadRequestException(
                    ErrorCode.RECORD_EXIST,
                    EscapeUtil.errorMessage("username", "该用户名已存在")
                );
            }
        } else {
            // 获取现有的管理员信息
            validateId(id);
            // 当新账户名与旧账户名不相同 并且查询新账户名在数据库中数量大于0时 即账户已经存在
            if (adminService.count(new QueryWrapper<AdminEntity>().eq("username", username).ne("id", id)) > 0) {
                throw new BadRequestException(
                    ErrorCode.RECORD_EXIST,
                    EscapeUtil.errorMessage("username", "该用户名已存在")
                );
            }
        }
    }
    
    private void validateId(Long id) {
        if (adminService.isEmpty(id)) {
            throw new BadRequestException(
                ErrorCode.RECORD_NOT_EXIST,
                EscapeUtil.errorMessage("id", "记录不存在")
            );
        }
    }
    
}
